package com.estate.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.estate.common.constant.RoleCategory;
import com.estate.common.core.domain.entity.SysUser;
import com.estate.common.core.domain.model.LoginUser;
import com.estate.common.utils.*;
import com.estate.system.domain.*;
import com.estate.system.domain.pojo.*;
import com.estate.system.mapper.*;
import com.estate.system.service.IClientRequirementService;
import com.estate.system.service.message.EmailGeneratorClientOkHttp;
import com.estate.system.service.message.TwilioSmsSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ClientRequirementServiceImpl extends ServiceImpl<ClientRequirementMapper, Client> implements IClientRequirementService {

    @Resource
    private ClientRequirementMapper clientRequirementMapper;

    @Resource
    private ClientRecListingsMapper clientRecListingsMapper;

    @Resource
    private DataListingsMapper dataListingsMapper;

    @Resource
    private DataContactsMapper dataContactsMapper;

    @Resource
    private MessageSendToClientImpl messageSendToClientImpl;


    @Resource
    private DataEnquiryMapper dataEnquiryMapper;

    @Resource
    private TwilioSmsSender twilioSmsSender;

    @Resource
    private EmailService emailService;

    @Resource
    private MessageSendToClientMapper messageSendToClientMapper;

    @Resource
    private EmailGeneratorClientOkHttp emailGeneratorClientOkHttp;

    @Resource
    private DataAgentMapper dataAgentMapper;

    @Resource
    private RoleCategory roleCategory;

    public Page<ClientRequirementVo> clientRequirementsPages(ClientRequirementVo clientRequirementVo) {
        //参数处理
        List<String> transactionTypes = clientRequirementVo.getTransactionTypes();
        if (transactionTypes != null && !transactionTypes.isEmpty()) {
            if (transactionTypes.contains("sale")) {
                transactionTypes.addAll(roleCategory.getBuyers());
            }
            if (transactionTypes.contains("lease")) {
                transactionTypes.addAll(roleCategory.getTenants());
            }
            if (transactionTypes.contains("auction")) {
                transactionTypes.addAll(roleCategory.getBidders());
            }
        }

        List<String> serviceTypes = clientRequirementVo.getServiceTypes();
        if (serviceTypes != null && !serviceTypes.isEmpty()) {
            if (serviceTypes.contains("lightservice")) {
                serviceTypes.add("light service");
            }
            if (serviceTypes.contains("deepservice")) {
                serviceTypes.add("deep service");
            }
        }

        Agent agent = getAgent();
        String enquiryType = "";
        if (agent != null) {
            clientRequirementVo.setAgentId(agent.getAgentId());
            enquiryType = "sales".equals(agent.getRole()) ? "sale" : "rentals".equals(agent.getRole()) ? "lease" : "sale";
        } else {
            return new Page<>();
        }
        Page<ClientRequirementVo> clientRequirements = clientRequirementMapper.clientRequirementsPages(PageUtils.getPage(clientRequirementVo), clientRequirementVo);
        //根据clientId查询房源推荐
        List<Long> clientIds = clientRequirements.getRecords().stream().map(ClientRequirementVo::getClientId).collect(Collectors.toList());
        if (!ObjectUtils.isEmpty(clientIds)) {
            List<ClientRecListings> clientRecListings = clientRecListingsMapper.selectList(new QueryWrapper<ClientRecListings>().lambda()
                    .in(ClientRecListings::getClientId, clientIds).eq(ClientRecListings::getClientListingType, enquiryType));
            //clientRecListings中的listingIdList按照","切分，获得数量
            Map<Long, Integer> clientRecListingsMap = clientRecListings.stream()
                    .collect(Collectors.toMap(
                            ClientRecListings::getClientId,
                            e -> {
                                if (e.getListingIdList() == null) {
                                    return 0;
                                }

                                List<Integer> listingIds = Arrays.stream(e.getListingIdList().split(","))
                                        .map(String::trim)
                                        .filter(s -> !s.isEmpty())
                                        // 兼容新旧格式：总是取第一个部分（冒号前或整个字符串）
                                        .map(item -> item.split(":")[0].trim())
                                        .filter(s -> !s.isEmpty())
                                        .map(Integer::valueOf)
                                        .distinct()
                                        .collect(Collectors.toList());

                                return listingIds.size();
                            },
                            // 当key重复时，累加value
                            Integer::sum
                    ));
            //迭代clientRequirements.getRecords()中的clientId，根据clientId查询clientRecListingsMap的对应的数量，并设置给clientRequirements中的recommendCount
            for (ClientRequirementVo clientRequirement : clientRequirements.getRecords()) {
                clientRequirement.setRecommendCount(clientRecListingsMap.get(clientRequirement.getClientId()));
            }
        }
        return clientRequirements;
    }

    private Agent getAgent() {
        try {
            log.info("=== 获取当前登录用户 ===");
            LoginUser loginUser = SecurityUtils.getLoginUser();
            SysUser user = loginUser.getUser();
            String email = user.getEmail();
            List<Agent> agents = dataAgentMapper.selectList(new QueryWrapper<Agent>().lambda().eq(Agent::getEmail, email));
            if (!agents.isEmpty()) {
                return agents.get(0);
            }
        } catch (Exception e) {
            log.error("获取当前登录用户失败: {}", e.getMessage());
            return null;
        }
        return null;
    }

    @Override
    public Page<ClientRecommendationsVo> clientRecommendationsPages(ClientRecommendationsVo clientRecommendationsVo) {
        try {
            log.info("=== 开始 clientRecommendationsPages 查询 ===");
            log.info("传入参数 clientId: {}", clientRecommendationsVo.getClientId());

            if (clientRecommendationsVo.getClientId() == null) {
                log.error("clientId 不能为空");
                return new Page<>();
            }

            // 查询 ClientRecListings
            List<ClientRecListings> clientRecListings = clientRecListingsMapper.selectList(new QueryWrapper<ClientRecListings>()
                    .lambda().eq(ClientRecListings::getClientId, clientRecommendationsVo.getClientId()));

            log.info("ClientRecListings 查询结果数量: {}", clientRecListings.size());
            if (!ObjectUtils.isEmpty(clientRecListings)) {
                clientRecListings.forEach(item -> {
                    log.info("ClientRecListings 数据 - id: {}, listingIdList: {}", item.getClientId(), item.getListingIdList());
                });
            }

            if (!ObjectUtils.isEmpty(clientRecListings)) {
                log.error("未找到 clientId: {} 的推荐列表", clientRecommendationsVo.getClientId());
                return new Page<>();
            }

            // 处理 listingIds - 兼容新旧格式
            List<Integer> listingIds = clientRecListings.stream()
                    .filter(Objects::nonNull)
                    .map(ClientRecListings::getListingIdList)
                    .filter(StringUtils::hasText)
                    .flatMap(listStr -> Arrays.stream(listStr.split(",")))
                    .map(String::trim)
                    .filter(s -> !s.isEmpty())
                    // 兼容新旧格式：总是取第一个部分（冒号前或整个字符串）
                    .map(item -> item.split(":")[0].trim())
                    .map(Integer::valueOf)
                    .distinct()
                    .collect(Collectors.toList());

            log.info("解析后的 listingIds: {}", listingIds);

            if (listingIds.isEmpty()) {
                log.warn("clientId: {} 的 listingIdList 为空或格式错误", clientRecommendationsVo.getClientId());
                return new Page<>();
            }

            clientRecommendationsVo.setListingIds(listingIds);

            // 执行分页查询
            Page<ClientRecommendationsVo> pageParam = PageUtils.getPage(clientRecommendationsVo);
            log.info("分页参数: page={}, size={}", pageParam.getCurrent(), pageParam.getSize());

            Page<ClientRecommendationsVo> result = clientRequirementMapper.clientRecommendationsPages(pageParam, clientRecommendationsVo);

            log.error("最终查询结果 - 总记录数: {}, 当前页记录数: {}",
                    result.getTotal(), result.getRecords().size());
            if (!result.getRecords().isEmpty()) {
                result.getRecords().forEach(record -> {
                    log.info("查询到房源: listingId={}, price={}",
                            record.getListingId(), record.getListingPrice());
                });
            }

            return result;

        } catch (Exception e) {
            log.error("分页查询异常", e);
            return new Page<>();
        }
    }

    @Override
    public Page<ClientInterestedVo> clientInterestedPages(ClientInterestedVo clientInterestedVo) {
        try {
            log.info("=== 开始 clientRecommendationsPages 查询 ===");
            log.info("传入参数 clientId: {}", clientInterestedVo.getClientId());

            if (clientInterestedVo.getClientId() == null) {
                log.error("clientId 不能为空");
                return new Page<>();
            }

            // 查询 enquiries
            List<Enquiry> enquiries = dataEnquiryMapper.selectList(new QueryWrapper<Enquiry>()
                    .lambda().eq(Enquiry::getContactId, clientInterestedVo.getClientId()));

            log.info("enquiries 查询结果数量: {}", enquiries.size());

            if (!ObjectUtils.isEmpty(enquiries)) {
                log.error("未找到 clientId: {} 的推荐列表", clientInterestedVo.getClientId());
                return new Page<>();
            }

            // 处理 listingIds
            List<Integer> listingIds = enquiries.stream().distinct().map(Enquiry::getListingId).collect(Collectors.toList());

            log.info("解析后的 listingIds: {}", listingIds);

            if (listingIds.isEmpty()) {
                log.warn("clientId: {} 的 listingIdList 为空或格式错误", clientInterestedVo.getClientId());
                return new Page<>();
            }

            clientInterestedVo.setListingIds(listingIds);

            // 执行分页查询
            Page<ClientInterestedVo> pageParam = PageUtils.getPage(clientInterestedVo);
            log.info("分页参数: page={}, size={}", pageParam.getCurrent(), pageParam.getSize());

            Page<ClientInterestedVo> result = clientRequirementMapper.clientInterestedPages(pageParam, clientInterestedVo);

            log.error("最终查询结果 - 总记录数: {}, 当前页记录数: {}",
                    result.getTotal(), result.getRecords().size());
            if (!result.getRecords().isEmpty()) {
                result.getRecords().forEach(record -> {
                    log.info("查询到房源: listingId={}, price={}",
                            record.getListingId(), record.getListingPrice());
                });
            }

            return result;

        } catch (Exception e) {
            log.error("分页查询异常", e);
            return new Page<>();
        }
    }

    @Override
    public List<MessageSendToClient> generateMessage(List<GenerateMessageVo> clientInterestedVos) {
        // 获取代理商信息
        Agent agent = getAgent();
        if (Objects.isNull(agent)) {
            log.warn("未生成任何消息");
            return new ArrayList<>();
        }
        // 使用 CompletableFuture 处理多线程
        List<CompletableFuture<Message2AddrVo>> futures = clientInterestedVos.stream()
                .map(vo -> CompletableFuture.supplyAsync(() -> processSingleMessage(vo, agent)))
                .collect(Collectors.toList());

        // 等待所有任务完成并获取结果
        List<Message2AddrVo> messageList = futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());

        // 保存草稿
        if (messageList.isEmpty()) {
            log.warn("未生成任何消息");
            return new ArrayList<>();
        }
        return saveDraftMessage(messageList);
    }

    private Message2AddrVo processSingleMessage(GenerateMessageVo clientInterestedVo, Agent agent) {
        Message2AddrVo message2AddrVo = new Message2AddrVo();

        String enquiryType;
        // 判断 enquiryType
        if (!ObjectUtils.isEmpty(agent)) {
            enquiryType = "sales".equals(agent.getRole()) ? "sale" : "rentals".equals(agent.getRole()) ? "lease" : "sale";
            clientInterestedVo.setAgentId(agent.getAgentId());
            clientInterestedVo.setEnquiryType(enquiryType);
        } else {
            log.error("未找到代理商信息");
            return null;
        }

        // 获取 listingIds,如果参数listingIds为空，则从数据库中获取
        if (ObjectUtils.isEmpty(clientInterestedVo.getListingIds())) {
            // 从数据库中获取推荐信息
            List<ClientRecListings> clientRecListings = clientRecListingsMapper
                    .selectList(new QueryWrapper<ClientRecListings>().lambda().eq(ClientRecListings::getClientId, clientInterestedVo.getClientId())
                            .eq(ClientRecListings::getClientListingType, enquiryType));

            // 处理 listingIds
            List<Integer> listingIds = new ArrayList<>();
            if (clientRecListings != null && !clientRecListings.isEmpty()) {
                clientRecListings.forEach(clientRecListing -> {
                    listingIds.addAll(Arrays.stream(clientRecListing.getListingIdList().split(","))
                            .map(String::trim)
                            .filter(s -> !s.isEmpty())
                            .map(item -> {
                                if (item.contains(":")) {
                                    // 新格式：2666958:0.8119 → 取冒号前部分
                                    return item.split(":")[0];
                                } else {
                                    // 旧格式：2666958 → 直接使用
                                    return item;
                                }
                            })
                            .map(Integer::valueOf)
                            .collect(Collectors.toList()));
                });
                clientInterestedVo.setListingIds(listingIds);
            }
        }

        // 获取邮件和短信信息
        String message = emailGeneratorClientOkHttp.generateEmail(clientInterestedVo);
        if (StringUtils.isEmpty(message)) {
            log.error("邮件生成失败");
            return null;
        }
        Map<String, String> result = parseMail(message);
        message2AddrVo.setClientId(clientInterestedVo.getClientId());
        message2AddrVo.setEmailSubject(result.get("subject"));
        message2AddrVo.setEmailMessage(result.get("emailContent"));
        message2AddrVo.setMobileMessage(result.get("smsContent"));
        message2AddrVo.setEmail(clientInterestedVo.getEmail());
        message2AddrVo.setMobile(clientInterestedVo.getMobile());
        message2AddrVo.setListingIds(clientInterestedVo.getListingIds());
        return message2AddrVo;
    }

    public Map<String, String> parseMail(String message) {
        JSONObject jsonObject = JSONObject.parseObject(message);
        Map<String, String> result = new HashMap<>();
        String emailContent = jsonObject.getString("email_content");
        String smsContent = jsonObject.getString("sms_content");

        // 按第一个"\n\n"分割subject和content
        int splitIndex = emailContent.indexOf("\n\n");
        String subjectLine;
        String emailMessage;

        if (splitIndex != -1) {
            subjectLine = emailContent.substring(0, splitIndex);
            emailMessage = emailContent.substring(splitIndex + 2); // +2 跳过\n\n
        } else {
            // 如果没有找到\n\n，整个内容作为subject
            subjectLine = emailContent;
            emailMessage = "";
        }

        // 从subject行中提取纯主题
        String subject = subjectLine.replace("Subject:", "").trim();
        result.put("subject", subject);
        result.put("emailContent", emailMessage);
        result.put("smsContent", smsContent);
        return result;
    }

    @Override
    public Map<String, Object> sendMessage(List<Message2AddrVo> message2AddrVos) {

        Map<String, Object> result = new HashMap<>();
        result.put("allClientSize", message2AddrVos.size());

        // 获取所有clientId
        List<Long> clientIds = message2AddrVos.stream().map(Message2AddrVo::getClientId).distinct().collect(Collectors.toList());
        List<Client> clients = dataContactsMapper.selectList(new QueryWrapper<Client>().lambda().in(Client::getClientId, clientIds));
        //获取所有客户名称Map
        Map<Long, String> clientNameMap = new HashMap<>();
        clients.forEach(client -> {
            clientNameMap.put(Long.valueOf(client.getClientId()), client.getFirstName() + " " + client.getLastName());
        });

        //获取所有的id
        List<Long> sendMessageIds = message2AddrVos.stream().map(Message2AddrVo::getId).distinct().collect(Collectors.toList());

        //查询暂存信息
        List<MessageSendToClient> messageSendToClients = messageSendToClientMapper.selectList(new QueryWrapper<MessageSendToClient>().lambda().in(MessageSendToClient::getId, sendMessageIds));

        //获取邮件记录 sendType = "email"
        List<MessageSendToClient> emailMessageSendToClients = messageSendToClients.stream().filter(messageSendToClient -> "email".equals(messageSendToClient.getSendType())).collect(Collectors.toList());

        //获取短信记录 sendType = "mobile"
        List<MessageSendToClient> mobileMessageSendToClients = messageSendToClients.stream().filter(messageSendToClient -> "mobile".equals(messageSendToClient.getSendType())).collect(Collectors.toList());

        List<Map<String, Object>> sendSMSFailedResultList = new ArrayList<>();
        List<Map<String, Object>> sendSMSSuccessResultList = new ArrayList<>();
        List<Map<String, Object>> sendEmailFailedResultList = new ArrayList<>();
        List<Map<String, Object>> sendEmailSuccessResultList = new ArrayList<>();
        // 获取发送内容
        mobileMessageSendToClients.forEach(messageSendToClient -> {
            // todo
            //boolean sendResult = twilioSmsSender.send(messageSendToClient.getSendAddr(), messageSendToClient.getMessage());
            boolean sendResult = twilioSmsSender.send("413027079", messageSendToClient.getMessage());

            Map<String, Object> sendResultMap = new HashMap<>();
            sendResultMap.put("clientId", messageSendToClient.getClientId());
            sendResultMap.put("clientName", clientNameMap.get(messageSendToClient.getClientId()));
            sendResultMap.put("phone", messageSendToClient.getSendAddr());
            if (!sendResult) {
                sendSMSFailedResultList.add(sendResultMap);
                //变更状态
                messageSendToClient.setStatus("failed");
                messageSendToClient.setSendAt(new Date());
            } else {
                sendSMSSuccessResultList.add(sendResultMap);
                //变更状态
                messageSendToClient.setStatus("sended");
                messageSendToClient.setSendAt(new Date());
            }
        });

        emailMessageSendToClients.forEach(messageSendToClient -> {
            // todo
            //boolean sendResult = emailService.sendHtmlEmail(messageSendToClient.getSendAddr(), "Handpicked Listings for Your Consideration", messageSendToClient.getMessage());
            boolean sendResult = emailService.sendHtmlEmail("15510096974@163.com",
                    StringUtils.isEmpty(messageSendToClient.getSubject()) ? "Handpicked Listings for Your Consideration" : messageSendToClient.getSubject(),
                    messageSendToClient.getMessage());
            emailService.sendHtmlEmail("zyl_nupt@126@com",
                    StringUtils.isEmpty(messageSendToClient.getSubject()) ? "Handpicked Listings for Your Consideration" : messageSendToClient.getSubject(),
                    messageSendToClient.getMessage());

            Map<String, Object> sendResultMap = new HashMap<>();
            sendResultMap.put("clientId", messageSendToClient.getClientId());
            sendResultMap.put("clientName", clientNameMap.get(messageSendToClient.getClientId()));
            sendResultMap.put("email", messageSendToClient.getSendAddr());
            if (!sendResult) {
                sendEmailFailedResultList.add(sendResultMap);
                //变更状态
                messageSendToClient.setStatus("failed");
                messageSendToClient.setSendAt(new Date());
            } else {
                sendEmailSuccessResultList.add(sendResultMap);
                //变更状态
                messageSendToClient.setStatus("sended");
                messageSendToClient.setSendAt(new Date());
            }

        });

        //保存
        messageSendToClientImpl.updateBatchById(emailMessageSendToClients);
        messageSendToClientImpl.updateBatchById(mobileMessageSendToClients);

        result.put("clientIds", clientIds);
        result.put("sendSMSSuccessResultList", sendSMSSuccessResultList);
        result.put("sendEmailSuccessResultList", sendEmailSuccessResultList);
        result.put("sendSMSFailedResultList", sendSMSFailedResultList);
        result.put("sendEmailFailedResultList", sendEmailFailedResultList);

        //返回ClientID
        return result;
    }

    @Override
    public List<MessageSendToClient> saveDraftMessage(List<Message2AddrVo> messageList) {
        Long batchNo = SnowflakeIdWorker.getSingleton().nextId();
        List<MessageSendToClient> messageSendToClientList = new ArrayList<>();
        for (Message2AddrVo message : messageList) {

            if (message.getMobile() != null) {
                MessageSendToClient messageSendToClient = ObjectUtils.isEmpty(message.getId()) ? new MessageSendToClient() : messageSendToClientMapper.selectById(message.getId());
                messageSendToClient.setClientId(message.getClientId());
                messageSendToClient.setSendType("mobile");
                messageSendToClient.setSendAddr(message.getMobile());
                messageSendToClient.setMessage(message.getMobileMessage());
                messageSendToClient.setCreatedAt(new Date());
                messageSendToClient.setStatus("draft");
                messageSendToClient.setCreatedBy(0L);
                messageSendToClient.setListingIds(JSONObject.toJSONString(message.getListingIds()));
                messageSendToClient.setBatchNo(batchNo + "");
                messageSendToClientList.add(messageSendToClient);
                if (message.getId() == null) {
                    messageSendToClient.setId(SnowflakeIdWorker.getSingleton().nextId());
                    messageSendToClientMapper.insert(messageSendToClient);
                } else {
                    messageSendToClientMapper.updateById(messageSendToClient);
                }
            }
            if (message.getEmail() != null) {
                MessageSendToClient messageSendToClient = ObjectUtils.isEmpty(message.getId()) ? new MessageSendToClient() : messageSendToClientMapper.selectById(message.getId());
                messageSendToClient.setClientId(message.getClientId());
                messageSendToClient.setSendType("email");
                messageSendToClient.setSendAddr(message.getEmail());
                messageSendToClient.setSubject(message.getEmailSubject());
                messageSendToClient.setMessage(message.getEmailMessage());
                messageSendToClient.setCreatedAt(new Date());
                messageSendToClient.setStatus("draft");
                messageSendToClient.setCreatedBy(0L);
                messageSendToClient.setListingIds(JSONObject.toJSONString(message.getListingIds()));
                messageSendToClient.setBatchNo(batchNo + "");
                messageSendToClientList.add(messageSendToClient);
                if (message.getId() == null) {
                    messageSendToClient.setId(SnowflakeIdWorker.getSingleton().nextId());
                    messageSendToClientMapper.insert(messageSendToClient);
                } else {
                    messageSendToClientMapper.updateById(messageSendToClient);
                }
            }


        }
        return messageSendToClientList;

    }

    @Override
    public List<Message2AddrVo> getDraftMessage(List<Long> sendMessageIds) {
        List<Message2AddrVo> message2AddrVos = new ArrayList<Message2AddrVo>();

        List<MessageSendToClient> messageEmailSends = messageSendToClientMapper.selectList(new QueryWrapper<MessageSendToClient>()
                .lambda().in(MessageSendToClient::getId, sendMessageIds));
        messageEmailSends.forEach(m -> {
            if (!ObjectUtils.isEmpty(m) && m.getSendType().equals("email")) {
                Message2AddrVo message2AddrVo = new Message2AddrVo();
                message2AddrVo.setClientId(m.getClientId());
                message2AddrVo.setEmail(m.getSendAddr());
                message2AddrVo.setEmailSubject(m.getSubject());
                message2AddrVo.setEmailMessage(m.getMessage());
                message2AddrVo.setListingIds(JSONObject.parseObject(m.getListingIds(), List.class));
                message2AddrVos.add(message2AddrVo);
            }
            if (!ObjectUtils.isEmpty(m) && m.getSendType().equals("mobile")) {
                Message2AddrVo message2AddrVo = new Message2AddrVo();
                message2AddrVo.setClientId(m.getClientId());
                message2AddrVo.setMobile(m.getSendAddr());
                message2AddrVo.setMobileMessage(m.getMessage());
                message2AddrVo.setListingIds(JSONObject.parseObject(m.getListingIds(), List.class));
                message2AddrVos.add(message2AddrVo);
            }
        });
        return message2AddrVos;
    }

    @Override
    public List<MessageSendToClient> clientContactRecord(Long clientId) {
        List<String> statusList = new ArrayList<>();
        statusList.add("sended");
        statusList.add("viewed");
        statusList.add("replied");
        return messageSendToClientMapper.selectList(new QueryWrapper<MessageSendToClient>()
                .lambda().eq(MessageSendToClient::getClientId, clientId).in(MessageSendToClient::getStatus, statusList).orderByDesc(MessageSendToClient::getCreatedAt));
    }

}